#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
编码分布优化器
根据不同编码字段的特征，设计符合实际情况的概率分布模型
"""

import json
import random
import math
from typing import Dict, List, Tuple

class DistributionOptimizer:
    """
    分布优化器，为不同编码字段设计合理的概率分布模型
    """
    
    def __init__(self):
        # 定义不同分布模型的权重配置
        self.distributions = {
            # 主题类型 - 使用正态分布，生活实用和情感表达更常见
            '主题类型': {
                'model': 'normal',
                'params': {
                    'options': ['学业分享', '生活实用', '文化体验', '情感表达', '身份认同', '娱乐创意', '价值输出'],
                    'peak_index': 1,  # 生活实用为峰值
                    'spread': 2.0,    # 分布宽度
                    'secondary_peak': 3,  # 情感表达为次峰值
                    'secondary_weight': 0.8  # 次峰值权重
                }
            },
            # 声音素材 - 使用幂律分布，博主原声占主导
            '声音素材': {
                'model': 'power_law',
                'params': {
                    'options': ['博主原声', '背景音乐', '音效素材', '文本转语音', '其他'],
                    'alpha': 1.5,    # 幂律指数
                    'scale_factor': 0.3  # 缩放因子
                }
            },
            # 场景设定 - 使用二项分布，生活场景和校园场景更常见
            '场景设定': {
                'model': 'binomial',
                'params': {
                    'options': ['校园场景', '生活场景', '社交场景', '文化场景', '其他'],
                    'p': 0.6,        # 成功概率
                    'success_indices': [0, 1]  # 校园和生活场景为成功结果
                }
            },
            # 视频情感倾向 - 使用泊松分布，中性和积极情绪更常见
            '视频情感倾向': {
                'model': 'poisson',
                'params': {
                    'options': ['积极正向', '消极负向', '中性客观'],
                    'lambda': 1.0,   # 泊松参数
                    'offset': 0      # 偏移量
                }
            },
            # 话题标签 - 使用贝塔分布，大多数视频会关联话题
            '话题标签': {
                'model': 'beta',
                'params': {
                    'options': ['关联或创建话题', '未关联或创建话题'],
                    'alpha': 5.0,    # 成功次数
                    'beta': 2.0      # 失败次数
                }
            },
            # 作者昵称类型 - 使用均匀分布，但略微偏向自身状态
            '作者昵称类型': {
                'model': 'adjusted_uniform',
                'params': {
                    'options': ['个人姓名', '自身状态', '其他'],
                    'weights': [0.3, 0.45, 0.25]  # 调整后的权重
                }
            },
            # 作者简介内容 - 使用多项式分布，经历介绍和个性签名更常见
            '作者简介内容': {
                'model': 'multinomial',
                'params': {
                    'options': ['经历介绍', '个性签名', '业务咨询', '其他'],
                    'probs': [0.4, 0.35, 0.15, 0.1]  # 多项式概率
                }
            }
        }
    
    def normal_distribution_weights(self, n: int, peak_index: int, spread: float, 
                                  secondary_peak: int = None, secondary_weight: float = 0.5) -> List[float]:
        """
        生成正态分布权重
        
        Args:
            n: 选项数量
            peak_index: 峰值位置
            spread: 分布宽度参数
            secondary_peak: 次峰值位置（可选）
            secondary_weight: 次峰值权重
            
        Returns:
            归一化的权重列表
        """
        weights = []
        for i in range(n):
            # 计算与峰值的距离
            distance = (i - peak_index) / spread
            # 正态分布公式
            weight = math.exp(-0.5 * distance ** 2)
            
            # 添加次峰值影响
            if secondary_peak is not None:
                secondary_distance = (i - secondary_peak) / spread
                secondary_contribution = math.exp(-0.5 * secondary_distance ** 2) * secondary_weight
                weight += secondary_contribution
            
            weights.append(weight)
        
        # 归一化
        total = sum(weights)
        return [w / total for w in weights]
    
    def power_law_distribution_weights(self, n: int, alpha: float, scale_factor: float) -> List[float]:
        """
        生成幂律分布权重
        
        Args:
            n: 选项数量
            alpha: 幂律指数
            scale_factor: 缩放因子
            
        Returns:
            归一化的权重列表
        """
        weights = []
        for i in range(n):
            # 幂律分布公式，索引从1开始
            weight = 1 / ((i + 1) ** alpha)
            weights.append(weight)
        
        # 归一化并应用缩放因子
        total = sum(weights)
        normalized_weights = [w / total for w in weights]
        
        # 应用缩放因子，使分布更平滑
        if scale_factor < 1.0:
            uniform_component = 1.0 / n
            for i in range(n):
                normalized_weights[i] = normalized_weights[i] * scale_factor + uniform_component * (1 - scale_factor)
            
            # 重新归一化
            total = sum(normalized_weights)
            normalized_weights = [w / total for w in normalized_weights]
        
        return normalized_weights
    
    def binomial_distribution_weights(self, n: int, p: float, success_indices: List[int]) -> List[float]:
        """
        生成二项分布风格的权重
        
        Args:
            n: 选项数量
            p: 成功概率
            success_indices: 成功结果的索引列表
            
        Returns:
            归一化的权重列表
        """
        weights = []
        for i in range(n):
            if i in success_indices:
                weights.append(p / len(success_indices))
            else:
                weights.append((1 - p) / (n - len(success_indices)))
        
        return weights
    
    def poisson_distribution_weights(self, n: int, lam: float, offset: int) -> List[float]:
        """
        生成泊松分布风格的权重
        
        Args:
            n: 选项数量
            lam: 泊松参数
            offset: 偏移量
            
        Returns:
            归一化的权重列表
        """
        weights = []
        for i in range(n):
            k = i + offset
            # 泊松分布公式
            weight = (lam ** k * math.exp(-lam)) / math.factorial(max(1, k))
            weights.append(weight)
        
        # 归一化
        total = sum(weights)
        return [w / total for w in weights]
    
    def beta_distribution_weights(self, n: int, alpha: float, beta: float) -> List[float]:
        """
        生成贝塔分布风格的权重
        
        Args:
            n: 选项数量
            alpha: 成功次数
            beta: 失败次数
            
        Returns:
            归一化的权重列表
        """
        # 简化版贝塔分布，主要用于二元分类
        if n == 2:
            p_success = alpha / (alpha + beta)
            return [p_success, 1 - p_success]
        else:
            # 对于多项分布，使用简化的权重分配
            weights = [0] * n
            weights[0] = alpha / (alpha + beta)
            remaining = 1 - weights[0]
            for i in range(1, n):
                weights[i] = remaining / (n - 1)
            return weights
    
    def adjusted_uniform_weights(self, weights: List[float]) -> List[float]:
        """
        调整后的均匀分布权重
        
        Args:
            weights: 预定义的权重列表
            
        Returns:
            归一化的权重列表
        """
        # 归一化权重
        total = sum(weights)
        return [w / total for w in weights]
    
    def multinomial_weights(self, probs: List[float]) -> List[float]:
        """
        多项式分布权重
        
        Args:
            probs: 概率列表
            
        Returns:
            归一化的权重列表
        """
        # 归一化概率
        total = sum(probs)
        return [p / total for p in probs]
    
    def get_weights_for_category(self, category: str) -> List[float]:
        """
        获取指定类目的权重分布
        
        Args:
            category: 编码类目名称
            
        Returns:
            权重列表
        """
        if category not in self.distributions:
            # 默认均匀分布
            return [1.0]
        
        dist_config = self.distributions[category]
        model = dist_config['model']
        params = dist_config['params']
        
        if model == 'normal':
            return self.normal_distribution_weights(
                len(params['options']),
                params['peak_index'],
                params['spread'],
                params.get('secondary_peak'),
                params.get('secondary_weight', 0.5)
            )
        elif model == 'power_law':
            return self.power_law_distribution_weights(
                len(params['options']),
                params['alpha'],
                params['scale_factor']
            )
        elif model == 'binomial':
            return self.binomial_distribution_weights(
                len(params['options']),
                params['p'],
                params['success_indices']
            )
        elif model == 'poisson':
            return self.poisson_distribution_weights(
                len(params['options']),
                params['lambda'],
                params['offset']
            )
        elif model == 'beta':
            return self.beta_distribution_weights(
                len(params['options']),
                params['alpha'],
                params['beta']
            )
        elif model == 'adjusted_uniform':
            return self.adjusted_uniform_weights(params['weights'])
        elif model == 'multinomial':
            return self.multinomial_weights(params['probs'])
        else:
            # 默认均匀分布
            return [1.0 / len(params['options'])] * len(params['options'])
    
    def get_distribution_info(self) -> Dict[str, Dict]:
        """
        获取所有分布的信息和权重
        
        Returns:
            包含分布信息和权重的字典
        """
        result = {}
        
        for category, config in self.distributions.items():
            weights = self.get_weights_for_category(category)
            options = config['params']['options']
            
            # 计算预期分布百分比
            distribution = {}
            for i, option in enumerate(options):
                distribution[option] = round(weights[i] * 100, 2)
            
            result[category] = {
                'model': config['model'],
                'distribution': distribution,
                'params': config['params']
            }
        
        return result

# 测试代码
if __name__ == "__main__":
    optimizer = DistributionOptimizer()
    dist_info = optimizer.get_distribution_info()
    
    print("各编码字段的理论分布模型和权重配置：")
    print(json.dumps(dist_info, ensure_ascii=False, indent=2))